這次做得功能類似to do list,不過只有增加及改變狀態的功能。
在開始之前我們需要先大致了解,本地的資料庫也就是F12=>Application下的Storage。
也是我們今天的重點,簡而言之就是本地儲存庫,格式為 key : value
,只能記較單純的資料類型,如數值、字串
,可以跨瀏覽器分頁做使用
、使用者關掉分頁或瀏覽器再打開資料仍不會消失
,且資料無期效限制,資料將永久被保留,除非我們手動作刪除
。
由於HTTP協定是無狀態的概念
,所以Server處理完我們的資料就不會記得我們所做的紀錄
、事情等,如我們在購物車購買東西,但是Server並不會知道我們買了什麼,此時就需要cookie,而cookie是由Web server端產生
的,作為發送给browser端,而當browser接收到Cookie後,會將其中的key/value
,保存
到某個路徑內的文本文件之中,讓下次於造訪同一網站時,就可以將Cookie自動發送给Web Server端
,像是local與server在交換時會帶有的內容,會在驗證、登入、購物車等情境下使用到
。
與session不同,session是存在server端
,Session storage存在本地端
,存在檔案或資料庫,搭配cookie使用
,生命週期較短,當使用者關掉瀏覽器或分頁時,sessionStorage 中的資料將被清空
。
首先就是獲取我們會用到的DOM元素,其中localStorage的資料獲取需要透過getItem getItem(keyName);
,且獲取的型態為字串
,所以要parse轉為JSON型式([{},{}...])
,預設值為空陣列。
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
// 利用getItem獲取localStorage中的資料
const items = JSON.parse(localStorage.getItem('items')) || [];
增添事件處理
// 送出增加列表事件
addItems.addEventListener('submit', addItem);
// 點擊列表狀態切換事件
itemsList.addEventListener('click', toggleDone);
createList(items, itemsList);
而增添事件的函數,是採submit觸發,由於submit本身會有預設的動作
,如跳轉到指定網址等,所以一開始需要加上e.preventDefault()來避免預設行為
,而後value是利用屬性篩選器來獲取(form底下有name="item"的DOM元素),
接著我們在將資料的值及狀態(done)以物件型式儲存。
而後push至我們的localStorage的資料陣列中,並利用setItem(setItem(keyName, keyValue);),來更新我們的localStorage資料
,且記得將我們已轉為JSON型式的資料字串化
,因為要傳回localStorage,而localStorage的資料都是以字串型式表示。
而這邊還使用了一個清除在form下input中value的一個方法,HTMLFormElement.reset(),可清除表單內的資料
。
// 在表單輸入資料並點擊增加之處理
function addItem(e) {
// 防止submit的預設行為(跳轉頁面...)
e.preventDefault();
// let value = this.querySelector('input:first-child').value;
let value = (this.querySelector('[name=item]')).value;
const obj = {
value,
done: false
};
// 將input輸入之資料push進陣列(更新)
items.push(obj);
// 更新Local資料
localStorage.setItem(
"items",
// 記得將資料字串化
JSON.stringify(items)
);
createList(items, itemsList); // 呼叫產生list(更新畫面)
// HTMLFormElement.reset() 可清除表單內的資料
this.reset();
// this.querySelector('[name=item]').value = "";
}
下面為產生列表的函數,記得最後要做join將 , 去除以空字串來隔開每筆資料。
// 第一個參數為資料,data=[]的用意,為賦予一個[]表示為預設值
// 第二個參數為我們要放置進去的DOM
function createList(data = [], platesList) {
// 將陣列中的物件拿出來處理
// 第一個參數為物件資料
// 第二個為下標
platesList.innerHTML = data.map((plate, index) => {
return `
<li>
<input type="checkbox" data-index=${index} id="item${index}" ${plate.done ? 'checked' : ''} />
<label for="item${index}">${plate.value}</label>
</li>
`;
}).join('');
}
切換狀態處理函數,由於target因為label的特性會觸發兩次,故我們利用matches來判斷目標是否為input, (element.matches(selectorString); 可檢查元素是否為指定選擇器,是返回true,反之false
),來判斷是否要繼續執行,而後在對應的列表進行狀態切換,最後別忘記更新我們的localStorage及畫面。
function toggleDone(e) {
console.log(e.target, e.currentTarget); // 發現target會重複觸發
// 判斷是否為Input,是的話才繼續(避免會重複觸發)
if (!e.target.matches('input')) return; // skip this unless it's an input
const el = e.target;
// 自定義屬性為data-index的DOM
const index = el.dataset.index;
// 切換其DOM的done狀態
items[index].done = !items[index].done;
// 更新local資料庫
localStorage.setItem('items', JSON.stringify(items));
// 更新畫面
createList(items, itemsList);
}